import singleton from "./singleton";
import cache from "./cache";

import {
	_splitInPairs,
	_ab2hex,
	createBuffer,
} from "./common.js"

const CODE = {
	"-1": "未知错误",
	0: "自定义错误",
	1000: "未初始化蓝牙",
	10001: "当前蓝牙不可用",
	10002: "没有找到指定设备",
	10003: "连接失败",
	10004: "没有找到指定服务",
	10005: "没有找到指定特征值",
	10006: "当前连接已断开",
	10007: "当前特征值不支持此操作",
	10008: "其余所有系统上报的异常",
	10009: "Android 系统特有",
	10010: "已连接",
	10011: "配对设备需要配对码",
	10012: "连接超时",
	10013: "连接 deviceId 为空或者是格式不正确",
}


//错误写入特征跳过
const WRITE_CACHE_NAME = "WRITE_CACHE_ARR";

let connect_interval;


let config = {
	deviceId: "",
	characteristic: {}
}

let serviceKey = 0;
//蓝牙主动断开定时器
let disconnect_timeout;
//蓝牙心跳
let interPing;

//蓝牙配置信息
let options = {}

function initOptions() {
	options.runStatus = {
		onStateChange: false,
		onValueChange: false,
		onValueFound: false,
		initState: false,
	}
	options.connected = false
}
initOptions()

const ble = function() {
	return new Class();
}
//蓝牙监听
ble.watch = (event, data) => {}
ble.error = (event, data) => {}


ble.debug = () => {
	console.log('--------debug--------', options)
}

//蓝牙主动断开定时器
ble.disconnect = (callback, ttl = 30) => {
	disconnect_timeout = setTimeout(() => {
		if (typeof callback == 'function') {
			callback()
		}
		ble.close()
		uni.switchTab({
			url: "/pages/tabbar/index/index"
		})
		//停止心跳
		ble.stopPing();
	}, ttl * 1000)
}

//蓝牙显示清除主动断开定时器
ble.show = () => {
	clearTimeout(disconnect_timeout)
}

//初始化蓝牙
ble.init = function(callback) {
	if (options.runStatus.initState == true) return;
	uni.openBluetoothAdapter({
		success(res) {
			console.log("初始化成功")
			options.runStatus.initState = true;
			if (typeof callback === "function") {
				setTimeout(callback, 1500)
			}
			ble.watch("open", {
				message: "初始化成功"
			})
			if (options.runStatus.onValueFound == false) {
				options.runStatus.onValueFound = true;
				uni.onBluetoothDeviceFound(function(d) {
					let data = d.devices[0];
					if (data.name != "") {
						ble.watch("search", data)
					}
				})
			}

			if (options.runStatus.onStateChange == false) {
				//监听低功耗蓝牙连接状态的改变事件。包括开发者主动连接或断开连接，设备丢失，连接异常断开等等
				options.runStatus.onStateChange = true;
				uni.onBLEConnectionStateChange(function(data) {
					options.connected = data.connected
					// if (data.connected) {
					// 	//清除定时器
					// 	clearInterval(connect_interval)
					// }
					clearInterval(connect_interval)
					ble.watch("state", data)
				})
			}

			if (options.runStatus.onValueChange == false) {
				options.runStatus.onValueChange = true;
				//监听低功耗蓝牙设备的特征值变化事件。
				uni.onBLECharacteristicValueChange(function(res) {
					let data = _ab2hex(res.value)
					data = data.replace(new RegExp('aa55', 'g'), '').replace(new RegExp('55aa',
						'g'), '');
					let arr = _splitInPairs(data)
					if (!arr) return false;
					// console.log("-------NOTIFY原始数据-------", data, arr)
					let n_data = arr.slice(2)
					ble.watch("notify", {
						status: arr[0],
						command: arr[1],
						// data: n_data
						data: n_data.length > 4 ? n_data.reverse() : n_data
					})
				})


			}
		},
		fail(e) {
			error("init", 0, "初始化失败")
			options.runStatus.initState = false;
		}
	})
}

//发送数据
ble.send = function(value, callback, ttl = 0) {
	setTimeout(() => {
		uni.writeBLECharacteristicValue({
			deviceId: config.deviceId,
			serviceId: config.characteristic.serviceId,
			characteristicId: config.characteristic.writeId,
			value,
			success(data) {
				ble.watch("send", {
					data
				})
				if (typeof callback === "function") {
					callback({
						type: "send",
						message: "发送成功",
						data
					});
				}
			},
			fail(e) {
				console.error('发送失败', e)
				error("send", e.code ?? e.errCode)
			}
		})
	}, ttl)

}

ble.stopPing = () => {
	clearInterval(interPing)
}
ble.ping = (command, ttl = 10) => {
	if (!command) console.error("指令不能为空");
	interPing = setInterval(() => {
		if (options.connected) ble.send(createBuffer(command));
	}, 1000 * ttl)
}

ble.closeAll = function(callback) {
	uni.closeBluetoothAdapter({
		success(res) {
			options.runStatus.initState = false;
			console.log(res)
			ble.stopPing();
			//初始状态
			// options.connected = false
		},
		complete() {
			if (typeof callback === "function") {
				callback()
			}
		}
	})
}

//关闭蓝牙
ble.close = function(callback) {
	clearInterval(connect_interval)
	//停止心跳
	ble.stopPing();
	options.connected = false;
	uni.closeBLEConnection({
		deviceId: config.deviceId,
		success() {
			ble.watch("close", {
				message: "关闭蓝牙成功"
			})
		},
		fail(e) {
			error('close', CODE[e.code])
			// initOptions()
		},
		complete() {
			clearInterval(connect_interval)
			if (typeof callback === "function") {
				callback()
			}
		}
	})
}

//开始搜索设备
ble.start = (callback) => {
	console.log("开始搜索设备")
	uni.startBluetoothDevicesDiscovery({
		success(res) {
			if (typeof callback === "function") {
				callback()
			}
		},
		fail(err) {
			console.log(2222, err)
		}
	})
}
//停止搜索
ble.stop = (callback) => {
	uni.stopBluetoothDevicesDiscovery({
		success() {
			console.log("停止搜索蓝牙设备")
		},
		complete() {
			if (typeof callback === "function") {
				callback()
			}
		}
	})
}

let devices_list = [];
ble.search = (callback) => {
	devices_list = [];
	uni.getBluetoothDevices({
		success(res) {
			for (let key in res.devices) {
				if (res.devices[key].name) {
					devices_list.push(res.devices[key])
				}
			}
			if (typeof callback == 'function') {
				callback(devices_list)
			}
		},
		fail(err) {
			ble.init()
		}
	})
}

// //查找已搜索到设备
// ble.search = (callback) => {
// 	uni.getBluetoothDevices({
// 		success(res) {
// 			if (typeof callback == "function") {
// 				callback(res.devices)
// 				ble.watch({
// 					type: "search",
// 					data: res.devices
// 				})
// 			}
// 		},
// 		fail(e) {
// 			error("search", _CODE[e.errCode])
// 		}
// 	})
// }

//蓝牙特征配置设置
ble.config = (data) => {
	if (!data.deviceId) {
		console.error("deviceId不能为空")
	}
	config.deviceId = data.deviceId;
	config.characteristic = data.characteristic || {}
	// config.key = data.key || "";
	config.properties = data.properties || function() {}
	config.serviceId = data.serviceId || "";
}

//连接蓝牙
ble.connect = function() {
	let time = 0;
	let max_time = 30;

	uni.getConnectedBluetoothDevices({
		success(res) {
			//未连接状态
			let is_connect = false
			for (let key in res.devices) {
				if (res.devices[key].deviceId == config.deviceId) {
					//已连接
					is_connect = true;
					break;
				}
			}
			//未连接重新连接
			if (!is_connect) {
				setTimeout(_run, 50)
			} else {
				setTimeout(_ => {
					ble.connect()
				}, 1000)
			}
		},
		fail(e) {
			if (e.code == 10000) {
				ble.init(_run)
			}
		}
	})

	function _run() {
		connect_interval = setInterval(() => {
			time++
			//清除定时器
			if (time >= max_time) {
				clearInterval(connect_interval)
				options.connected = false;
				return;
			}
			let remainder = max_time - time
			ble.watch("state2", {
				connected: false,
				message: `未激活设备，${remainder}秒后退出连接`,
				remainder
			})
		}, 1000)


		uni.createBLEConnection({
			deviceId: config?.deviceId,
			success() {
				setTimeout(_ => {
					_getServiceId()
				}, 800)
			},
			fail(e) {
				options.connected = false
				//断开连接
				ble.close()
				// error("connection", e.code ?? e.errCode)
				error("quit", e.code ?? e.errCode, '连接失败')
			},
			complete() {
				clearInterval(connect_interval)
			}
		})
	}

}

let servcie_all = [];

const _getServiceId = () => {
	uni.getBLEDeviceServices({
		deviceId: config?.deviceId,
		success(res) {
			//直接传输无需直接获取
			if (config.characteristic?.serviceId && config.characteristic?.notifyId && config.characteristic
				?.writeId) {
				console.log('跳过自动搜索蓝牙特征')
				//开启广播
				setTimeout(_openNotify, 500)
				return false;
			}
			servcie_all = res.services;
			_getCharacteristics()
		},
		fail(e) {
			error("quit", e.code ?? e.errCode, '获取设备失败')
			// error("services", e.code ?? e.errCode)
			quit('获取设备失败')
		}
	})
}

const _handleServiceID = () => {
	if (config.serviceId) return config.serviceId;

	let services = servcie_all[serviceKey];
	if (serviceKey > 3) {
		error("services", 0, "获取特征错误")
		quit('获取设备失败')
		return false;
	}
	return services.uuid;
}

const _getCharacteristics = () => {
	config.characteristic.serviceId = _handleServiceID();
	uni.getBLEDeviceCharacteristics({
		deviceId: config.deviceId,
		serviceId: config.characteristic.serviceId,
		success(res) {
			for (let _obj of res.characteristics) {
				//获取writeId
				if (_obj.properties.write && config.properties('write', _obj.uuid)) {
					console.log("write获取成功")
					config.characteristic.writeId = _obj.uuid;
				}
				//获取notify
				if (_obj.properties.notify && config.properties('notify', _obj.uuid)) {
					config.characteristic.notifyId = _obj.uuid;
					console.log("notify获取成功")
				}

			}
			if (!config.characteristic.writeId || !config.characteristic.notifyId) {
				serviceKey++
				setTimeout(_ => {
					_getCharacteristics()
				}, 500)
				return false;
			}
			//开启广播
			_openNotify()
		},
		fail(e) {
			error("quit", e.code ?? e.errCode, '连接失败')
		}
	})
}

const _openNotify = () => {
	uni.notifyBLECharacteristicValueChange({
		state: true,
		deviceId: config?.deviceId,
		serviceId: config?.characteristic.serviceId,
		characteristicId: config?.characteristic.notifyId,
		success(res) {
			ble.watch('start', {
				message: "广播已启",
				data: res
			})
			console.log('------------', config)
			//清除定时器
			clearInterval(connect_interval)
			//更改连接状态
			options.connected = true;
		},
		fail(e) {
			error("quit", e.code ?? e.errCode, '连接失败')
			// quit('连接失败')
		}
	})
}


const error = (event, code, msg) => {
	ble.error(event, {
		code,
		msg: msg || CODE[code]
	})

	//错误蓝牙特征加入缓存 并且跳过此特征
	// if (code == 10007 || code == 10005) {
	// 	let tz = cache.get(WRITE_CACHE_NAME) || []

	// 	tz.push(config.characteristic.writeId)
	// 	cache.put(WRITE_CACHE_NAME, tz)
	// }
}


// 判断是否有蓝牙权限
ble.checkBlePermission = () => {

	// uni.getSetting({
	// 	success(res) {
	// 		if (!res.authSetting['scope.bluetooth']) {
	// 			// 没有权限，发起权限请求
	// 			uni.authorize({
	// 				scope: 'scope.bluetooth',
	// 				success() {

	// 				},
	// 				fail() {
	// 					// 用户拒绝了权限请求
	// 					// uni.showModal({
	// 					// 	title: '系统提示',
	// 					// 	content: '此功能需要蓝牙权限，请设置打开权限',
	// 					// 	success: (modalRes) => {
	// 					// 		if (modalRes.confirm) {
	// 					// 			uni.openSetting(); // 引导用户打开设置页面
	// 					// 		}
	// 					// 	}
	// 					// });
	// 				}
	// 			});
	// 		}
	// 	},
	// 	fail() {}
	// });
}




export default singleton(ble)